package com.jxtti.interceptor;

import java.io.IOException;
import java.util.Enumeration;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;

public class XSSCheckFilter implements Filter {
	private FilterConfig config; 
    private static String errorPath;//出错跳转的目的地 
    private static String[] excludePaths;//不进行拦截的url     
	private static String[] safeless = {
			"<script", // 需要拦截的JS字符关键字
			"</script", "<iframe", "</iframe", "<frame", "</frame",
			"set-cookie", "%3cscript", "%3c/script", "%3ciframe", "%3c/iframe",
			"%3cframe", "%3c/frame", "src=\"javascript:", "<body", "</body",
			"%3cbody", "%3c/body", "alert", "script", "document",
			"document.title", "document.write", "eval", "prompt",
			"onreadystatechange", "javascript", "msgbox","confirm","append",")"
	// "<",
	// ">",
	// "</",
	// "/>",
	// "%3c",
	// "%3e",
	// "%3c/",
	// "/%3e"
	};

	
	
	public void doFilter(ServletRequest req, ServletResponse resp,FilterChain filterChain) throws IOException, ServletException {    
        Enumeration params = req.getParameterNames(); //获得所有请求参数名
        HttpServletRequest request = (HttpServletRequest) req; 
        HttpServletResponse response = (HttpServletResponse) resp; 
        //String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + "/"; 
                 
        boolean isSafe = true; 
        String requestUrl = request.getRequestURI(); //获取页面请求路径
        //String queryUrl = request.getQueryString(); 
        //System.out.println("params:" + params + " , requestUrl:" + requestUrl + " , queryUrl" + queryUrl); 
        if(!excludeUrl(requestUrl)) {  
	        if(isSafe(requestUrl)) { //先校验url中是否含有特殊字符
	            requestUrl = requestUrl.substring(requestUrl.indexOf("/"));  //校验参数中的特殊字符
	            if(!excludeUrl(requestUrl)) { 
	                while (params.hasMoreElements()) { 
	                    String cache = req.getParameter((String) params.nextElement()); 
	                    if(StringUtils.isNotBlank(cache)) { 
	                        if(!isSafe(cache)) { 
	                            isSafe = false; 
	                            break; 
	                        } 
	                    } 
	                } 
	            } 
	        }else { 
	            isSafe = false; 
	        } 
        } 
                 
        if(!isSafe) { 
            request.setAttribute("err", "您输入的参数有非法字符，请输入正确的参数！"); 
            request.getRequestDispatcher(errorPath).forward(request, response); 
            return; 
        } 
        filterChain.doFilter(req, resp); 
    }
	

	//判断是否安全url
	private static boolean isSafe2(String str) {
		if (StringUtils.isNotBlank(str)) {
			for (String s : safeless) {
				String[] strs = str.split("/");
				for (String urlStr : strs) {
					if (s.equals(urlStr.toLowerCase())) {
						return false;
					}
				}
			}
		}
		return true;
	}
	
	private static boolean isSafe(String str) { 
        if(StringUtils.isNotBlank(str)) {     
            for (String s : safeless) { 
                if(str.toLowerCase().contains(s)) { 
                    return false; 
                } 
            } 
        } 
        return true; 
    } 
	
	private boolean excludeUrl(String url) {
		if (excludePaths != null && excludePaths.length > 0) {
			for (String path : excludePaths) {				
				if(url.contains(path)) {
					return true;
				}
			}
		}
		return false;
	}
	
	private boolean excludeUrl2(String url) {
		if (excludePaths != null && excludePaths.length > 0) {
			for (String path : excludePaths) {
				if (url.equals(path)) {
					return true;
				}
			}
		}
		return false;
	}	
	
	public void destroy() {
	}

	//初始化 获取xml中配置的 出错页面，包含路径等，
	public void init(FilterConfig config) throws ServletException {
		this.config = config;
		errorPath = config.getInitParameter("errorPath");
		String excludePath = config.getInitParameter("excludePaths");
		if (StringUtils.isNotBlank(excludePath)) {
			excludePaths = excludePath.split(",");
		}
	}
	
	
}
